//
//  IndexView.swift
//  browser
//
//  Created by Kotori on 2021/6/9.
//

import SwiftUI
import WebKit
import UIKit
//TODO

struct IndexView: View {
    //IndexView ID，用于外界Controller识别
    var uuid: UUID
    
    var indexCallback: IndexCallback?
    
    //是否在首页，控制首页搜索栏和常去网站的显示
    @State var isIndex: Bool = true
    //是否处于WebView导航状态，控制刷新按钮与停止按钮的现实
    @State var isLoading: Bool = false
    @State var isBookmark: Bool = false
    //目前正在访问的URL，控制顶部地址栏的展示
    @State var currURL: String = ""
    //页面内嵌WebView
    @State var webView: WebViewWrapper = WebViewWrapper()
    //当前打开的窗口数量，OnAppear刷新
    @State var tabCount:Int = 1
    //导航按钮可拖动使用
    @State var 导航按钮偏移量: CGSize = CGSize.zero
    @State var 导航按钮上一次的偏移量: CGSize = .zero
    
    @State private var naviBtn:IndexNaviButton = IndexNaviButton(btnDelegate: nil)
    
    /*
     只能创建IndexView时注入
     */
    
    var wdToload:String?
    
    var body: some View {
        ZStack {
            webView.setWebViewDelegate(delegate: self).padding(.top, 50)
            
            if isIndex {
                withAnimation {
                    Color.white.ignoresSafeArea()
                }
            }
            
            VStack {
                //首页顶栏
                IndexMenuBar(currURL: $currURL, isLoading: $isLoading,isBookmarked: $isBookmark, tabCount: tabCount, indexCallback: indexCallback, indexBtnDelegate: self, tabSwitchAction: {
                    //在进入标签切换页前传入一次标签元数据
                    indexCallback?.setTabItemAttribute(id:self.uuid,title: webView.title, urlStr: currURL, logo: nil, snapshot: webView.snapshot)
                }).onAppear {
                    //回调获取窗口数量
                    tabCount = indexCallback?.getTabCount() ?? tabCount
                }
       
                Spacer()
                
                //在首页，显示首页搜索框
                if isIndex {
                    IndexContentView(indexCallback: indexCallback, btnDelegate: self)
                    Spacer()
                    Spacer()
                }
            }.onDisappear {
                //进入其他界面，传入标签元数据
                indexCallback?.setTabItemAttribute(id: self.uuid, title: webView.title, urlStr: currURL, logo: webView.favicon, snapshot: webView.snapshot)
            }
            
            GeometryReader { 几何读取器 in
                naviBtn.offset(导航按钮偏移量)
                    .gesture(DragGesture()
                                .onChanged({ 拖动手势 in
                                    var temp = 导航按钮偏移量
                                    
                                    temp.width = 导航按钮上一次的偏移量.width + 拖动手势.translation.width
                                    temp.height = 导航按钮上一次的偏移量.height + 拖动手势.translation.height
                                    
                                    //尔杰把这个值硬编码了，按钮高度我就直接写进来了吧
                                    //.frame(width: 110, height: 50, alignment: .center)
                                    导航按钮偏移量.width = max(0,min(temp.width, 几何读取器.size.width-110))
                                    导航按钮偏移量.height = max(0, min(temp.height,几何读取器.size.height-50))
                                })
                                .onEnded({ gesture in
                                    导航按钮上一次的偏移量 = 导航按钮偏移量
                                })
                    ).onAppear{
                        if( 导航按钮上一次的偏移量 == .zero){
                            if naviBtn.btnDelegate == nil {
                                naviBtn.btnDelegate = self
                            }
                            导航按钮偏移量.width = 导航按钮偏移量.width+几何读取器.size.width*0.615
                            导航按钮偏移量.height = 导航按钮偏移量.height+几何读取器.size.height*(0.5+0.5*0.615)
                            导航按钮上一次的偏移量 = 导航按钮偏移量
                        }
                    }
            } //end geometry reader
        } //end zstack
        .onFirstAppear({
            if let wd = wdToload {
                self.loadURL(urlStr: wd)
            }
        })
    } //end body
    
    

    
}

extension IndexView: IndexBtnDelegate {
    //使WebView加载urlStr中网址
    func loadURL(urlStr: String) {
        //空串无事发生
        if !urlStr.isEmpty {
            /*
             若该方法在**非Body中**被调用，无法修改这个index值，同时对currURL的更改也是无效的
             对于 @State 修饰的属性的访问，只能发生在 body 或者 body 所调用的方法中。
             你不能在外部改变 @State 的值，只能@State初始化时，设置初始化值，如注释1处所示，它的所有相关操作和状态改变都应该是和当前 View 生命周期保持一致。
             */
            currURL = urlStr
            isIndex = false
            webView.loadRequest(urlStr: UrlUtil.getVaildHttpUrl(url: urlStr))
        }
    }
    
    //后退按钮点击回调事件
    func goBack() {
        //如果webView可以返回就返回，返回不了显示首页
        if(!webView.goBack()) {
            isIndex = true
            currURL = ""
        }
    }
    
    func goForward() {
        if(isIndex) {
            //在首页, 且已经有正在浏览的界面，则把首页撤掉
            if let url = webView.webView.url {
                isIndex = false
                currURL = url.absoluteString
            }
        } else if (webView.goForward()) {
            //前进成功
        }
    }
    
    func stopLoading() {
        webView.webView.stopLoading()
        isLoading(loading: false)
    }
    
    func reload() {
        webView.webView.reload()
    }
    
    func bookmark(isDelete: Bool) {
        if let url = webView.webView.url?.absoluteString {
            if isDelete {
                indexCallback?.deleteBookmark(urlStr: url)
            } else {
                indexCallback?.addBookmark(title: webView.title, urlStr: url, faviconData: webView.favicon?.pngData(), toBookmarkParentUuid: nil)
            }
        }
    }
    
    func isBookmarked() -> Bool {
        if let url = webView.webView.url?.absoluteString, let callback = indexCallback {
            return callback.isBookmarked(url: url)
        }
        return false
    }
    
    func goToSearchView() {
        var url:String?
        var title:String?
        if !isIndex {
            title = webView.webView.title
            url = webView.webView.url?.absoluteString
        } else {
            title = "首页"
            url = ""
        }
        indexCallback?.goToView(to: .SearchView, from: .IndexView, intent: .Default, with: [.url:url as Any,.title:title as Any])
    }
}

extension IndexView: WebViewDelegate {
    
    //WebView Favicon图标改变时回调 传到Tab切换界面以及历史记录管理器中
    func onFaviconChanged(favicon: UIImage?) {
        self.indexCallback?.setTabItemAttribute(id: self.uuid, title: nil, urlStr: currURL, logo: favicon, snapshot: self.webView.snapshot)
        addHistory(title: webView.title ?? "", url: currURL)
    }
    
    func onLoadStart(who webView: WKWebView, navigation: WKNavigation) {
        
    }
    
    //WebView 加载完毕回调 将标题和url传递到Tab切换界面 不传Favicon
    func onLoaded(who webView: WKWebView, navigation: WKNavigation) {
        self.indexCallback?.setTabItemAttribute(id: self.uuid, title: self.webView.title, urlStr: self.currURL, logo: nil, snapshot: self.webView.snapshot)
        isBookmark = isBookmarked()
    }
    
    /*
     错误发生时，webview内部回调结束
     */
    func onFailed(who webView: WKWebView, failWith navigation: WKNavigation, error: Error) {
        
    }
    
    func urlChanged() {
        YRNKLog("webViewDelegate currURL", msg:currURL+"error:\(webView.errorHappen)" )
        if !webView.errorHappen{
            //由于要显示错误页，但错误页url不需要显示出来
            currURL = webView.webView.url?.absoluteString ?? ""
        }
        isIndex = false
    }
    
    func isLoading(loading: Bool) {
        self.isLoading = loading
    }
    
    //addHistory 调用条件需要注意，加载的错误页不需要作为一条历史记录加入
    func addHistory(title: String, url: String) {
        HistoryManager.addHistory(title: title, url: url, pngData: webView.favicon?.pngData())
    }
    
    func openLinkInNewTab(link: URL) {
        //indexCallback?.goToView(by: .IndexView, sender: self, with: [RequestArgumentKey.wd.rawValue:link.absoluteString])
        //使用新接口
        indexCallback?.goToView(to: .IndexView, from: .IndexView, intent: .openNewTabOnIndexView, with: [.wd:link.absoluteString])
    }
    

    func previewImage(index: Int, imageUrls: [ImageInfo]) {
        YRNKSharedThreadPool.dispatchUITask {
            indexCallback?.goToView(to: .ImageViewer, from: .IndexView, intent: .Default,
                                    with:
                                        [.index:index,
                                         .imageUrls:imageUrls])
        }
    }
}



struct IndexView_Previews: PreviewProvider {
    static var previews: some View {

        IndexView(uuid:UUID())

    }
}
